﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Media.Imaging;
using EPiServer.ImageLibrary;

namespace OpenWaves.ImageTransformations.EPiServer
{
    public class EPiImageTransformationService : IImageTransformationService
    {
        private readonly IImageService imageService;

        public EPiImageTransformationService(IImageService imageService)
        {
            this.imageService = imageService;
        }

        public void TransformImage(Stream input, Stream output, ImageFormat outputFormat, IImageTransformation transformation)
        {
            using (var inputStream = input.CopyToMemoryStream())
            {
                var photoDecoder = BitmapDecoder.Create(
                    inputStream,
                    BitmapCreateOptions.PreservePixelFormat,
                    BitmapCacheOption.None);
                var photo = photoDecoder.Frames[0];

                var operationsWrapper = new ImageServiceOperationsWrapper(
                    photo.PixelWidth, 
                    photo.PixelHeight);

                transformation.ApplyToImage(operationsWrapper);

                var renderImage = this.imageService.RenderImage(
                    inputStream.GetBuffer(),
                    operationsWrapper.Operations, 
                    GetContentType(outputFormat), 
                    1,      // zoom 1 = 100%
                    90);    // jpg quality %

                output.Write(renderImage, 0, renderImage.Length);
            }
        }

        private static string GetContentType(ImageFormat outputFormat)
        {
            switch(outputFormat)
            {
                case ImageFormat.Jpeg:
                    return ContentTypes.Image.Jpeg;
                case ImageFormat.Png:
                    return ContentTypes.Image.Png;
                default:
                    throw new ArgumentOutOfRangeException("outputFormat");
            }
        }

        private class ImageServiceOperationsWrapper : IImage
        {
            private int width;
            private int height;

            private readonly IList<ImageOperation> operations = new List<ImageOperation>();
            public IEnumerable<ImageOperation> Operations
            {
                get { return this.operations; }
            }

            public int Width
            {
                get { return this.width; }
            }

            public int Height
            {
                get { return this.height; }
            }

            public ImageServiceOperationsWrapper(int width, int height)
            {
                this.width = width;
                this.height = height;
            }

            public void Scale(int newWidth, int newHeight)
            {
                this.operations.Add(new ImageOperation(ImageEditorCommand.Resize, newWidth, newHeight));

                this.width = newWidth;
                this.height = newHeight;
            }

            public void Crop(int left, int top, int newWidth, int newHeight)
            {
                this.operations.Add(new ImageOperation(ImageEditorCommand.Crop, newWidth, newHeight) { Left = left, Top = top});

                this.width = newWidth;
                this.height = newHeight;
            }
        }
    }
}